﻿//******************************************************************************************************
//  GEPOutputAdapter.cs - Gbtc
//
//  Copyright © 2013, Grid Protection Alliance.  All Rights Reserved.
//
//  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
//  the NOTICE file distributed with this work for additional information regarding copyright ownership.
//  The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
//  not use this file except in compliance with the License. You may obtain a copy of the License at:
//
//      http://www.opensource.org/licenses/eclipse-1.0.php
//
//  Unless agreed to in writing, the subject software distributed under the License is distributed on an
//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
//  License for the specific language governing permissions and limitations.
//
//  Code Modification History:
//  ----------------------------------------------------------------------------------------------------
//  04/15/2013 - Stephen C. Wills
//       Generated original version of source code.
//
//******************************************************************************************************

using System;
using System.Collections.Generic;
using System.Linq;
using SIEGate.Core;
using SIEGate.Core.Adapters;
using SIEGate.Core.Legacy;
using SIEGate.Core.Measurements;

namespace GSF.TimeSeries.Transport
{
    public class GEPOutputAdapter : OutputAdapter
    {
        #region [ Members ]

        // Nested Types

        public class AdapterInfo : AdapterInfoBase
        {
        }

        // Constants
        private const MeasurementStateFlags DataRangeMask = MeasurementStateFlags.OverRangeError | MeasurementStateFlags.UnderRangeError | MeasurementStateFlags.AlarmHigh | MeasurementStateFlags.AlarmLow | MeasurementStateFlags.WarningHigh | MeasurementStateFlags.WarningLow;
        private const MeasurementStateFlags DataQualityMask = MeasurementStateFlags.BadData | MeasurementStateFlags.SuspectData | MeasurementStateFlags.FlatlineAlarm | MeasurementStateFlags.ComparisonAlarm | MeasurementStateFlags.ROCAlarm | MeasurementStateFlags.ReceivedAsBad | MeasurementStateFlags.CalculationError | MeasurementStateFlags.CalculationWarning | MeasurementStateFlags.ReservedQualityFlag;
        private const MeasurementStateFlags TimeQualityMask = MeasurementStateFlags.BadTime | MeasurementStateFlags.SuspectTime | MeasurementStateFlags.LateTimeAlarm | MeasurementStateFlags.FutureTimeAlarm | MeasurementStateFlags.UpSampled | MeasurementStateFlags.DownSampled | MeasurementStateFlags.ReservedTimeFlag;
        private const MeasurementStateFlags SystemIssueMask = MeasurementStateFlags.SystemError | MeasurementStateFlags.SystemWarning | MeasurementStateFlags.MeasurementError;
        private const MeasurementStateFlags CalculatedValueMask = MeasurementStateFlags.CalcuatedValue;
        private const MeasurementStateFlags DiscardedValueMask = MeasurementStateFlags.DiscardedValue;

        #endregion

        #region [ Constructors ]

        public GEPOutputAdapter(IAdapterInfo adapterInfo)
            : base(adapterInfo)
        {
        }

        #endregion

        #region [ Methods ]

        /// <summary>
        /// Handles the measurements provided to this adapter for processing.
        /// </summary>
        /// <param name="measurements">The measurements to be processed.</param>
        protected override void HandleMeasurements(IEnumerable<IMeasurement> measurements)
        {
            CompactMeasurement[] compactMeasurements = measurements.Select(m => new CompactMeasurement()
            {
                SignalID = m.StreamID,
                StateFlags = MapToCompactFlags(m.StateFlags),
                Timestamp = m.Timestamp,
                Value = Convert.ToSingle(m.Value.GetRaw())
            }).ToArray();

            m_statsCluster.AddToCounter(StrStatProcessedMeasurements, compactMeasurements.Length);

           OnEmit(new RawData(OutgoingStreamIDs.First(), new DataPublisherValue(compactMeasurements)));
        }

        /// <summary>
        /// Not implemented. Measurements are handled by <see cref="HandleMeasurements"/>.
        /// </summary>
        /// <param name="m">The measurement that is not handled.</param>
        protected override void HandleMeasurement(IMeasurement m)
        {
            // Necessary if this is even implemented: m_statsCluster.AddToCounter(StrStatProcessedMeasurements, 1);
            throw new NotImplementedException();
        }

        #endregion

        #region [ Static ]

        // Static Methods

        /// <summary>
        /// Maps <see cref="MeasurementStateFlags"/> to <see cref="CompactMeasurementStateFlags"/>.
        /// </summary>
        /// <param name="stateFlags">Flags to map.</param>
        /// <returns><see cref="CompactMeasurementStateFlags"/> mapped from <see cref="MeasurementStateFlags"/>.</returns>
        private static CompactMeasurementStateFlags MapToCompactFlags(MeasurementStateFlags stateFlags)
        {
            CompactMeasurementStateFlags mappedStateFlags = CompactMeasurementStateFlags.NoFlags;

            if ((stateFlags & DataRangeMask) > 0)
                mappedStateFlags |= CompactMeasurementStateFlags.DataRange;

            if ((stateFlags & DataQualityMask) > 0)
                mappedStateFlags |= CompactMeasurementStateFlags.DataQuality;

            if ((stateFlags & TimeQualityMask) > 0)
                mappedStateFlags |= CompactMeasurementStateFlags.TimeQuality;

            if ((stateFlags & SystemIssueMask) > 0)
                mappedStateFlags |= CompactMeasurementStateFlags.SystemIssue;

            if ((stateFlags & CalculatedValueMask) > 0)
                mappedStateFlags |= CompactMeasurementStateFlags.CalculatedValue;

            if ((stateFlags & DiscardedValueMask) > 0)
                mappedStateFlags |= CompactMeasurementStateFlags.DiscardedValue;

            return mappedStateFlags;
        }

        #endregion
    }
}
